﻿
namespace Patterns4Net.PatternEnforcer.Core.Patterns
{
    using System.Linq;
    using Attributes;
    using Patterns4Net.Core.CecilExtensions;
    using Patterns4Net.Core.Patterns;

    public class WrapperChecker<TPattern> : FluentPatternChecker<TPattern> where TPattern : class, IPattern, IWrapper
    {
        public WrapperChecker()
        {
            this.If(pattern => pattern.TargetInterface != null)
                .Check(pattern => pattern.WrapperType.Implements(pattern.TargetInterface),
                    WrapperDoesNotImplementTargetError);

            this.If(pattern => pattern.WrappedType != null)
                .Check(HasFieldOfType, HasNotFieldOfTypeError);
        }

        private static string WrapperDoesNotImplementTargetError(TPattern pattern)
        {
            return string.Format(
                ErrorMessages.WrapperDoesNotImplementTarget, 
                pattern.WrapperType.Name, 
                pattern.TargetInterface.Name);
        }

        private static bool HasFieldOfType(TPattern pattern)
        {
            return pattern.WrapperType.HasFields &&
                   pattern.WrapperType.Fields.Any(x => x.FieldType.IsEqual(pattern.WrappedType));
        }

        private static string HasNotFieldOfTypeError(TPattern pattern)
        {
            return string.Format(
                ErrorMessages.WrapperDoesNotContainWrappedType, 
                pattern.WrapperType.Name, 
                pattern.WrappedType.Name);
        }
    }

    [PatternCheckerExport(typeof(Adapter))]
    public class AdapterChecker : WrapperChecker<Adapter>
    {        
    }

    [PatternCheckerExport(typeof(Decorator))]
    public class DecoratorChecker : WrapperChecker<Decorator>
    {
    }

    [PatternCheckerExport(typeof(Bridge))]
    public class BridgeChecker : WrapperChecker<Bridge>
    {
    }
}
